package edu.pku.sei.transformation.mdtocl;

import java.io.IOException;

import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.ocl.OCL;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.ecore.EcoreEnvironmentFactory;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.helper.OCLHelper;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;

import edu.pku.sei.transformation.constraint.ConstraintEngine;
import edu.pku.sei.transformation.editor.views.colors.ColorProvider;
import edu.pku.sei.transformation.editor.views.console.ConsoleViewManager;
import edu.pku.sei.transformation.util.ECoreModelSaveLoader;

public class MDTOCLEngine extends ConstraintEngine {
	private Resource modelResource = null;
	private EObject context = null;
	private OCL ocl = null;
	private OCLHelper helper = null;
	private MessageConsole console = null;
	private MessageConsoleStream stdout = null;
	private MessageConsoleStream errout = null;
	@Override
	public boolean init(String metaModelPath, String modelPath) {
		super.init(metaModelPath, modelPath);
		try {
			modelResource = ECoreModelSaveLoader.loadUseEcoreMetaModel(metaModelPath, modelPath);
			context = modelResource.getContents().get(0);
			if (context == null)
				return false;
			ocl =  OCL.newInstance(
					new EcoreEnvironmentFactory(
							new DelegatingPackageRegistry(
									context.eResource().getResourceSet().getPackageRegistry(),
									EPackage.Registry.INSTANCE)));
			helper = ocl.createOCLHelper();
			Object contextClassifier = context.eClass();
			if (contextClassifier == null) {
				return false;
			}
			helper.setContext(contextClassifier);
			
			console = ConsoleViewManager.getConsole(getEngineName());
			stdout = console.newMessageStream();
			errout = console.newMessageStream();
			errout.setColor(ColorProvider.RED);
			
		} catch (IOException e) {
			e.printStackTrace();
			errout.println(e.getMessage());
			return false;
		}
		return true;
	}
	
	@Override
	public boolean checkConstraint(String constraint) {
		String result = evaluate(constraint);
		if (result.equals("true"))
			return true;
		else
			return false;
	}

	@Override
	public String evaluate(String expression) {
		try {
			ConsoleViewManager.showView();
			stdout.println("Expression:");
			stdout.println(expression);
			stdout.println("Result:");
			
			OCLExpression<EClassifier> parsed = helper.createQuery(expression);
			String result = ocl.evaluate(context, parsed).toString();
			
			stdout.println(result);
			return result;
		} catch (ParserException e) {
			e.printStackTrace();
			errout.println(e.getMessage());
			return "evaluate failed +" + e.getMessage();
		}
	}

	@Override
	public String getEngineName() {
		return "MDT OCL";
	}
}
